﻿using System;
using System.Reflection;
using System.Collections.Generic;
using Infrastructure.ServicesManager.Configuration;
using Infrastructure.Diagnostics;

namespace Infrastructure.ServicesManager
{
    class ServiceEngine : IServiceEngine
    {
        struct ServiceProperties
        {
            public string Name;
            public Type Type;
            public object[] CtorArgs;
        }

        private Dictionary<string, ServiceProperties> m_services = new Dictionary<string, ServiceProperties>();
        private Dictionary<string, object> m_instances = new Dictionary<string, object>();

        public void Init()
        {
            ServicesManagerSection serviceEngineConfiguration =
            System.Configuration.ConfigurationManager.GetSection("ServicesManagerConfiguration") as ServicesManagerSection;

            ServicesCollectionElement services = serviceEngineConfiguration.Services;
           
            foreach (ServiceElement serviceElement in services)
            {
                Assembly assembly = Assembly.Load(serviceElement.Assembly);
                foreach (Type type in assembly.GetTypes())
                {
                    try
                    {
                        IServiceInitializer initializer = Activator.CreateInstance(type) as IServiceInitializer;
                        if (initializer != null)
                        {
                            initializer.Initialize();
                        }
                    }
                    catch (Exception e)
                    {
                        System.Diagnostics.Debug.WriteLine(e.Message);
                    }
                }
            }
        }

        public void RegisterService<_Type>(string name, params object[] args)
        {
            if (m_services.ContainsKey(name)) return;
            ServiceProperties sp = new ServiceProperties();
            sp.Name = name;
            sp.Type = typeof(_Type);
            sp.CtorArgs = args;
            m_services.Add(name, sp);
        }

        public void UnregisterService(string name)
        {
            if (!m_services.ContainsKey(name)) return;
            m_services.Remove(name);
            if (m_instances.ContainsKey(name)) m_instances.Remove(name);
        }

        public _Interface GetService<_Interface>(string name)
        {
            if (m_instances.ContainsKey(name)) return (_Interface)m_instances[name];
            _Interface service = (_Interface)Activator.CreateInstance(m_services[name].Type, m_services[name].CtorArgs);
            m_instances.Add(name, service);
            return (_Interface)service;
        }

        public bool IsServiceAvailable<_Interface>()
        {
            foreach (ServiceProperties property in m_services.Values)
            {
                if (property.Type == typeof(_Interface)) return true;
            }
            return false;
        }

        public bool IsServiceAvailable(string name)
        {
            return m_services.ContainsKey(name);
        }
    }
}